home *** CD-ROM | disk | FTP | other *** search
- ;***
- ;
- ;STICKRT.ASM
- ;Turbo Pascal Joystick Interface Module
- ;(C)Copyright Gerard Paul Java 1996
-
- ;Interface Source File
- ;
- ;This file contains joystick routines for use by Turbo Pascal 5.0 and later
- ;programs. These provide Pascal with a joystick interface. The StickCoord
- ;and StickButtonDown routines are to be declared in Pascal as functions as:
- ;
- ; function StickCoord(AxisCode: byte): byte; external;
- ; function StickButtonDown(ButtonCode: byte): boolean; external;
- ;
- ;For StickCoord, pass a value of 1 for the X-coordinate of stick A, 2 for
- ;the Y-coordinate of stick A, 4 for the X-coordinate of stick B, 16 for the
- ;Y-coordinate of stick B.
- ;
- ;For StickButtonDown, pass a value of 16 for button 1 on stick A, 32 for
- ;button 2 on stick A, 64 for button 1 on stick B, 128 for button 2 on stick
- ;B. Returns TRUE if the button is up, FALSE if pressed.
- ;
- ;Assemble with the Borland Turbo Assembler 1.0 or later.
- ;
- ;This module is designed to be linked into Turbo Pascal units, and these
- ;routines are intended to be declared in the interface sections. The
- ;routines therefore make use of the FAR call model.
-
- ;Note to programmers: arguments passed from Pascal correspond to the bit
- ;values involved. Therefore, when the StickCoord function takes 4 for its
- ;argument, it checks the status of the third bit. This is done for speed
- ;and efficiency.
- ;
- ;These routines access the joystick data directly from port 201H. It does
- ;not make use of the BIOS INT 15h Service 84h. These routines will therefore
- ;work on the PCs and XTs. However, this also requires that the computer be
- ;100% hardware-compatible with the PC family.
- ;
- ;This is the layout of the byte received from port 201H:
- ;
- ; 128 64 32 16 8 4 2 1 <--- place values
- ; 1 1 1 1 1 1 1 1
- ; ^ ^ ^ ^
- ; | | | |
- ;Button B2 status ---+ | | |
- ;Button B1 status -------+ | |
- ;Button A2 status -----------+ |
- ;Button A1 status ---------------+
- ;
- ;Each button status bit is high (1) when its respective button is up, low (0)
- ;when down.
- ;
- ;The remaining bits are high (1) for a certain period, depending on the
- ;shaft positions on their corresponding axes, after which they go low (0).
- ;The time during which the bits are high corresponds to the shaft positions
- ;on their corresponding axes. This can be determined using a program loop.
- ;
- ;Bit 3 corresponds to axis Y2, bit 2 to axis X2, bit 1 to axis Y1, and bit 0
- ;to axis X1.
- ;
- ;The shaft positions increase with CPU speed. This characteristic is
- ;present in all software using joysticks. The selection for 20000 as the
- ;"not found" value is based on the fact that no joystick reaches that value,
- ;even with the fastest CPUs.
- ;
- ;The other routines have comment headers explaining their functions.
- ;Declare them as:
- ;
- ; function StickIsPresent(StickCode: boolean): boolean; external;
- ; procedure InitAndCheckGameSys(var ErrCode: boolean); external;
- ;;
- ;These routines will work with any device connected to the standard IBM game
- ;port. Such devices must use the same technology as the IBM-compatible
- ;joysticks. As much as possible, the detection routines provide for
- ;violation of the IBM specs, for example, if another device or adapter uses
- ;port 201H for purposes other than what IBM dictated. Such conditions may
- ;be interpreted as error conditions, but no guarantee is given.
- ;
- ;***
- ;
-
- MAXCOUNT EQU 20000 ;Maximum count for stick.
- GAMEPORT EQU 201H ;Game port.
-
- .MODEL TPASCAL ;Turbo Pascal interface module.
-
- .CODE
-
- PUBLIC StickCoord ;Make routines available.
- PUBLIC StickButtonDown
- PUBLIC StickIsPresent
- PUBLIC InitAndCheckGameSys
-
-
- ;--------------------------------------------------------------------------
- ;StickCoords: Returns the specified joystick position. From Turbo Pascal,
- ;pass 1 for X1, 2 for Y1, 4 for X2, and 8 for Y2.
- ;
- ;Function returns word value in AX, interpreted as word from Pascal.
- ;Minimum return value is 0, although chances are that the minimum will
- ;be higher, considering the speeds of PCs nowadays.
- ;
- ;BX,CX,DX destroyed.
- ;--------------------------------------------------------------------------
-
- StickCoord PROC FAR AxisCode: BYTE
- MOV BL,AxisCode ;Load parameter into BL.
- MOV CX,MAXCOUNT ;Load max count.
- MOV DX,GAMEPORT ;Adapter I/O data port.
- SETTLE_WAIT: IN AL,DX ;Wait for bit to settle.
- TEST AL,BL
- LOOPNZ SETTLE_WAIT
- JCXZ TOO_HIGH ;Resistance too high, done.
- MOV CX,1FFH ;Delay a bit
- DELAY: JMP SHORT $+2
- JMP SHORT $+2
- JMP SHORT $+2
- LOOP DELAY
- MOV CX,MAXCOUNT
- OUT DX,AL ;Start joystick timers.
- CLI ;Interrupts off, plus settle.
- XOR CX,CX ;Initialize counter.
- TIME_STICK: IN AL,DX ;Read byte.
- TEST AL,BL ;Bit high?
- JZ DONE ;Inc CX if done, done if no.
- INC CX ;Increase CX
- CMP CX,MAXCOUNT ;Resistance too high?
- JE TOO_HIGH ;Yes, done.
- JMP SHORT $+2 ;Really big delay to stabilize.
- JMP SHORT $+2
- JMP SHORT $+2
- JMP TIME_STICK ;Yes, loop until low or CXZ.
- DONE: STI ;Interrupts back on.
- MOV AX,CX ;Store maxcount in AX.
- SHR AX,1 ;Divide by 2, for less vibr.
- RET ;Return to caller.
- TOO_HIGH: MOV AX,MAXCOUNT ;Return maxcount if error.
- RET
- StickCoord ENDP
-
- ;
- ;---------------------------------------------------------------------------
- ;StickButtonDown: Returns the status of the specified button. From Turbo
- ;Pascal, pass 16 or A1, 32 for A2, 64 for B1, and 128 for B2. Returns True
- ;if pressed, False of up.
- ;
- ;Returns a byte value in AL, interpreted as boolean from Pascal.
- ;
- ;DX destroyed.
- ;--------------------------------------------------------------------------
- ;
- StickButtonDown PROC FAR ButtonCode: BYTE
- MOV DX,GAMEPORT ;Point to game port.
- IN AL,DX ;Read joystick.
- TEST AL,ButtonCode ;Bit high?
- JNZ NOT_PRESSED ;Yeah, not pressed
- MOV AL,1 ;else pressed, return True.
- RET ;Return to caller.
- NOT_PRESSED: XOR AL,AL ;Return False if button up.
- RET ;Return to caller.
- StickButtonDown ENDP
-
-
- ;--------------------------------------------------------------------------
- ;StickIsPresent: Determines whether the specified stick is present. If any
- ;or both of the resistive inputs stay high for too long, or if from low,
- ;suddenly go high without signalling, it indicates an absence of the stick.
- ;
- ;Pass 0201H to check for stick A, 0804H to check for stick B.
- ;
- ;Returns a byte value in AL, interpreted as boolean from Pascal.
- ;
- ;BX,CX,DX destroyed.
- ;--------------------------------------------------------------------------
-
- StickIsPresent PROC FAR TestBy: WORD
- TEST_X_AXIS: MOV BX,TestBy ;Load detection parameter.
- MOV CX,MAXCOUNT ;Max count
- MOV DX,GAMEPORT ;Load in port address.
- OUT DX,AL ;Start 558/556 one-shots.
- READ_PORT1: IN AL,DX ;Read adapter.
- TEST AL,BL ;Low?
- LOOPNZ READ_PORT1 ;No, loop till so.
- JCXZ TEST_Y_AXIS ;High too long; try Y axis.
- JMP STICK_PRESENT ;Gone low, must be present.
- TEST_Y_AXIS: MOV CX,MAXCOUNT ;Reload max count.
- OUT DX,AL ;Restart one-shots.
- READ_PORT2: IN AL,DX ;Read adapter.
- TEST AL,BH ;Low?
- LOOPNZ READ_PORT2 ;Loop until so.
- JCXZ STICK_ABSENT ;Still high, error.
- STICK_PRESENT: MOV AL,1
- RET
- STICK_ABSENT: XOR AL,AL
- RET
- StickIsPresent ENDP
-
-
- ;---------------------------------------------------------------------------
- ;This procedure tests whether there are any game devices attached to the
- ;PC. If an adapter is present, the bits don't go low if their corresponding
- ;joysticks are not present, so if this happens, the joystick is absent.
- ;If they do go low, another check is conducted to see if any of them go high
- ;even if not triggered. If they do, the adapter is not present, and
- ;therefore, no joysticks.
- ;
- ;Returns a byte value in a variable parameter, interpreted as boolean from
- ;Pascal.
- ;
- ;AX,CX,DX destroyed.
- ;---------------------------------------------------------------------------
-
- InitAndCheckGameSys PROC FAR ErrCodeAddr: DWORD
- LES DI,ErrCodeAddr
- MOV DX,GAMEPORT ;Game adapter I/O.
- MOV CX,MAXCOUNT ;Load count.
- OUT DX,AL ;Start one-shots.
- CHECK_STICKS: IN AL,DX ;Read adapter.
- AND AL,0FH ;Zero upper bits.
- CMP AL,0FH ;Check for changes.
- LOOPE CHECK_STICKS ;Loop while none.
- JCXZ NEG_CHECK ;Still high, error.
- MOV CX,MAXCOUNT ;Reload count.
- MOV BL,AL ;Transfer last bits to BL.
- RECHECK: IN AL,DX ;Reread port.
- AND AL,0FH
- CMP AL,BL ;Changes?
- LOOPE RECHECK ;Loop while none.
- JCXZ OK ;No changes since, ok.
- JB OK ;Changes, from high to low, ok.
- NEG_CHECK: MOV BYTE PTR ES:[DI],01 ;But from low to high, no way.
- RET
- OK: MOV BYTE PTR ES:[DI],00 ;No error return 0, 1 otherwise.
- RET
- InitAndCheckGameSys ENDP
-
- END
-
-